<?php
require_once('LuceneXml.class.php');
require_once('PortalData.class.php');

class P_Portal 
{
    private $_action;
    private $_dataArray;
    private $_data_to_lucene = array();
    private $_db_type;
    private $_programme_id;
    private $_episode_id;

	public $change_log;

	/*
	 * by donald
	 */
    public function setData($data)
    {
		$this->change_log = array();
		$action = strtolower($data['action']);
        $this->_action = $action;

		if ($action == 'p_publish') {
			$type = $data['callback_data']['type'];
			$id = $data['callback_data']['id'];

			if (!empty($data['callback_data']['change_log'])) { //new flow
				$this->change_log = $data['callback_data']['change_log'];
				switch ($type) {
					case 'p_programme':
						$programme_id = $id;
						$episode_id = 0;
						break;
					case 'p_episode':
						$programme_id = 0;
						$episode_id = $id;
						break;
					default:
						exit('wrong type');
						break;
				}
				$this->_dataArray = NewPortalData::getPortalData($data['callback_data']['change_log'], $programme_id, $episode_id);
			} else { //old flow
				switch ($type) {
					case 'p_programme':
						$this->_dataArray = PortalData::getPortalData('p_programme', $id);
						break;
					case 'p_episode':
						$this->_dataArray = PortalData::getPortalData('p_episode', $id);
						break;
				}
			}

			file_put_contents('/tmp/portal_change_log', var_export($data['callback_data']['change_log'], TRUE));
			file_put_contents('/tmp/portal_p_proofread_data.txt', var_export($this->_dataArray, TRUE));
			//change array to object
			$this->_dataArray = json_decode(json_encode($this->_dataArray));	
		} elseif ($action == 'p_unpublish') {
			//change array to object
			$this->_dataArray = json_decode(json_encode($data['callback_data']['unpublish_items']));
		}
    }

	/*
	 * by donald
	 */
    public function receive()
    {
		Model::$dbo['r'] = Model::$dbo['w'];
		Model::$dbo['w']->beginTransaction();

        try {
            $this->recevieStart();

            Model::$dbo['w']->commit();

            return TRUE;
        } catch (PDOException $e) {
            //file_put_contents('/tmp/portal_pdo.txt', print_r($e, 1));
            Model::$dbo['w']->rollback();
            mail(CommonUtils::getAdminMail(), 'PortalReceive error.', print_r($e, 1));

            return FALSE;
        } catch (LUCException $e) {
            //file_put_contents('/tmp/portal_luc.txt', print_r($e, 1));
            Model::$dbo['w']->rollback();
            mail(CommonUtils::getAdminMail(), 'PortalReceive error.', print_r($e, 1));

            return FALSE;
        }
    }

    public function recevieStart()
    {
        if ($this->_action == 'p_publish') {
            $this->removeOldValue($this->change_log);
            $this->portalPublish();
        } else {
            $this->portalUnpublish();
        }
        $this->sendXmlToLucene();
    }

    public function subRecevie()
    {
        if ($this->_action == 'p_publish') {
            $this->portalPublish();
        } else {
            $this->portalUnpublish();
        }
		return $this->_data_to_lucene;
    }

    public function sendXmlToLucene()
    {
        $lucene = new LuceneXml;
        foreach ($this->_data_to_lucene as $operation=>$datas) {
            foreach ($datas as $type=>$data) {
                if (!empty($data)) {
                    $data = $this->formateDataLucene($type, $data);
                    $file = $lucene->newLuceneXml($type, $data, $operation);
                    $lucene->addXmlNeedPush($type, $file);
                }
            }
        }
        $lucene->pushXmlToLuceneServer();
    }

    public function portalPublish()
    {
		error_log("\n".'========== portal-p_publish ==========');
        foreach ($this->_dataArray as $type=>$objects) {
            foreach ($objects as $object) {
                if (!empty($object)) {
                    $this->publish($type, $object);
                }
            }
        }
		error_log('======================================');
    }

	/*
	 * by donald
	 * modified at 2011-11-07
	 */
	public function removeOldValue($change_log_list)
	{
		foreach ($change_log_list as $change_log) {
			if (!empty($change_log['is_active'])) {
				continue;
			}
			switch ($change_log['type']) {
				case 'folder':
					$p_folder->id = $change_log['keys']['id'];
					$this->unpublish('p_folder', $p_folder);
					break;
				case 'folder_item': // bug 7681
					$folder_id = $change_log['keys']['folder_id'];
					$item_id = $change_log['keys']['item_id'];

					$p_folder_video_list = p_folder_video::getAll(
						array(
							'folder_id' => $folder_id,
							'video_id' => $item_id
						)
					);
					foreach ($p_folder_video_list as $p_folder_video) {
						$this->unpublish('p_folder_video', $p_folder_video);
					}

					if (empty($p_folder_video_list)) {
						$p_folder_image_list = p_folder_image::getAll(
							array(
								'folder_id' => $folder_id,
								'image_id' => $item_id,
							)
						);
						foreach ($p_folder_image_list as $p_folder_image) {
							$this->unpublish('p_folder_image', $p_folder_image);
						}
					}
					break;
				case 'image':
					$p_image->id = $change_log['keys']['id'];
					$this->unpublish('p_image', $p_image);
					break;
				case 'video':
					$p_video->id = $change_log['keys']['id'];
					$this->unpublish('p_video', $p_video);
					break;
				case 'cast':
					$p_cast->id = $change_log['keys']['id'];
					$this->unpublish('p_cast', $p_cast);
					break;
				case 'chapter':
					$p_chapter->id = $change_log['keys']['id'];
					$this->unpublish('p_chapter', $p_chapter);
					break;
				case 'info_address':
				case 'info_award':
				case 'info_biography':
				case 'info_general_information':
				case 'info_pageant':
				case 'info_product':
				case 'info_q_a':
				case 'info_recipe':
				case 'info_song':
					$p_info->info_type_id = AC::$info_type_id[$change_log['type']];
					$p_info->info_id = $change_log['keys']['id'];
					$this->unpublish('p_info', $p_info);
					break;
				default:
					break;
			}
		}
	}

    public function checkOldImageForProgramme($image_id, $programme_id, $episode_id='0')
    {
        $folder_image = new p_folder_image;
        $images = $folder_image->findFolderImageByImageId($image_id, $programme_id, $episode_id);
        if (!empty($images)) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    public function portalUnpublish()
    {
		$this->flag_unpublish_programme = array_key_exists('p_programme', $this->_dataArray) ? 1 : 0;

		error_log("\n".'========== portal-p_unpublish ==========');
        foreach ($this->_dataArray as $type=>$objects) {
			error_log("\t" . $type);
            foreach ($objects as $object) {
                if (!empty($object)) {
                    $this->unpublish($type, $object);
                }
            }
        }
		error_log('========================================');
    }

    public function publish($type, $object)
    {
        $object_record = new $type;

        switch ($type) {
        case 'p_folder_video':
            $object_record = $object_record->get(array($object->folder_id, $object->video_id));
			error_log($type . ': ' . $object->folder_id . ',' . $object->video_id);
            break;
        case 'p_folder_image':
            $object_record = $object_record->get(array($object->folder_id, $object->image_id));
			error_log($type . ': ' . $object->folder_id . ',' . $object->image_id);
            break;
        case 'p_info':
            $object_record = $object_record->get(array($object->info_id, $object->info_type_id));
			error_log($type . ': ' . $object->info_id . ',' . $object->info_type_id);
            break;
        default:
            $object_record = $object_record->get($object->id);
			error_log($type . ': ' . $object->id);
            break;
        }

        if (empty($object_record)) {
            $object_record = new $type;
            $object_record->set($object);
            $object_record->insert($object_record);            
            $operation = 'add';
        } else {
            $object_record->set($object);
            if (property_exists($object_record, 'last_modified')) {
                unset($object_record->last_modified);
            }
            $object_record->update($object_record);
            $operation = 'edit';
        }

        $data = $this->formatData($operation, $type, $object);
        $this->addData($operation, $type, $data);
    }

    public function unpublish($type, $object)
    {
        $operation = 'del';
        $object_record = new $type;
        if ($type == 'p_video') {
            $p_video_detail = $object_record->get($object->id);
			if (empty($p_video_detail)) {
				return;
			}
        }
        $object_record->set($object);
        $object_record->delete($object_record);

        if ($type == 'p_video' && !$this->flag_unpublish_programme) {
            $this->republishEpisode($p_video_detail->episode_id);
        }

        $data = $this->formatData($operation, $type, $object);
        $this->addData($operation, $type, $data);
    }

    public function addData($operation, $type, $data)
    {
        $this->_data_to_lucene[$operation][$type][] = $data;
    }

    public function formatData($operation, $type, $object)
    {
        switch ($type) {
        case 'p_folder_image':
            $data = $this->formateDataFolderImage($operation, $object);
            break;
        case 'p_folder_video':
            $data = $this->formateDataFolderVideo($operation, $object);
            break;
        case 'p_info':
            $data = $this->formateDataInfo($operation, $object);
            break;
        default:
            $data = (array) $object;
            break;
        }

        return $data;
    }

    public function formateDataFolderImage($operation, $object)
    {
        switch ($operation) {
        case 'add':
        case 'edit':
            $object->id = $object->folder_id . '_' . $object->image_id;
            $data = (array) $object;
            break;
        case 'del':
            $data = array(
                'id' => $object->folder_id . '_' . $object->image_id
            );
            break;
        }

        return $data;
    }

    public function formateDataFolderVideo($operation, $object)
    {
        switch ($operation) {
        case 'add':
        case 'edit':
            $object->id = $object->folder_id . '_' . $object->video_id;
            $data = (array) $object;
            break;
        case 'del':
            $data = array(
                'id' => $object->folder_id . '_' . $object->video_id
            );
            break;
        }

        return $data;
    }

    public function formateDataInfo($operation, $object)
    {
        switch ($operation) {
        case 'add':
        case 'edit':
            $object->id = $object->info_id . '_' . $object->info_type_id;
            $data = (array) $object;
            break;
        case 'del':
            $data = array(
                'id' => $object->info_id . '_' . $object->info_type_id
            );
            break;
        }

        return $data;
    }

    public function formateDataLucene($type, $data)
    {
        if (empty($this->_db_type[$type])) {
            $this->getDbType($type);
        }

        foreach ($data as $key=>$row) {
            foreach ($row as $field=>$value) {
                if (!isset($this->_db_type[$type][$field]['type'])) {
                    continue;
                }
                switch ($this->_db_type[$type][$field]['type']) {
                case 'datetime':
                    break;
                case 'timestamp':
                    $data[$key][$field] = date('Y-m-d\TH:i:s\Z', (int) $row[$field]);
                    break;
                case 'int':
				case 'bit':
				case 'bigint':
				case 'tinyint':
				case 'smallint':
                    $data[$key][$field] = $row[$field] ? $row[$field] : 0; 
                    break;
                default:
                    break;
                }
            }
        }

        return $data;
    }

    public function getDbType($table_name)
    {
        $sql = "desc ".$table_name;
        $ret = Model::selectBySql($sql);
        foreach ($ret as $row) {
            $this->_db_type[$table_name][strtolower($row['Field'])] = array(
                'type' => preg_replace('/\((?!\)).+\)+/','',$row['Type']),
                'null' => ($row['Null']=='YES'),
                'default' => $row['Default']
            );
        }
    }

	/*
	 * by donald
	 */
    public function republishEpisode($episode_id)
    {
		if (empty($episode_id)) {
			return;
		}	

		$class = __CLASS__;
		$_this = new $class;
		$_this->setData(
			array(
				'action' => 'p_publish', 
				'callback_data' => array(
					'type' => 'p_episode', 
					'id' => $episode_id
				)
			)
		);
		$data_to_lucene = $_this->subRecevie();
		foreach ($data_to_lucene as $operation => $datas) {
			foreach ($datas as $type => $data) {
				foreach ($data as $arr) {
					$this->addData($operation, $type, $arr);
				}
			}
		}
    }
}
?>
